package de.latzko.pattern.util
import java.util.Random
import java.util.Random._


sealed abstract class Distribution;
case class N(val mu:Double,sigma:Double) extends Distribution
case class U(val min:Double, val max:Double) extends Distribution
case class UInt(val num:Int) extends Distribution

object RandomNumber {
	def apply() = new RandomNumber()
}

class RandomNumber {
	private val rand = new Random();
	private var func  = () => rand.nextDouble()
	
	def ~(dist: Distribution):Unit = {
		dist match {
			case N(m,s) => func = () => rand.nextGaussian() * s + m
			case U(min,max) => func = () => rand.nextDouble() * (max - min) + min
			case UInt(n) => func  = () => rand.nextInt(n)
			case _ => func = () => rand.nextDouble()
		}
	}
	
	def test(dist: Distribution):Any = {
		dist match {
			case N(m,s) => return () => (rand.nextGaussian() * s + m)
			case U(min,max) => return () => (rand.nextDouble() * (max - min) + min)
			case UInt(n) => return () => rand.nextInt(n)
			case _ => return () => rand.nextDouble()
		}
	}
	
	def apply():AnyVal = func()
	
	/**
	 * Operators 
	 * @param x
	 * @return func %op% x
	 */
	def +( x : Double ):Double = x + func()
	def -(x:Double) = func() - x
	def *(x:Double) = func() * x
	//def +:() = func()
	def unary_-(x:Double) = x - func()
	def unary_*(x:Double) = x * func()
	
	def >(x:Double):Boolean = func() > x
	def >=(x:Double):Boolean = func() >= x
	def <(x:Double):Boolean = func() < x
	def <= (x:Double):Boolean = func() <= x
	def =:(x:Double ) = func()
	
	def !():AnyVal = func()
}